#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include "laserparams.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    cardUtil = new CardUtil();
    cardUtil->start();
    configParam.readFromFile();
    rtcCardsGroup = new QActionGroup(this);
    connect(rtcCardsGroup, &QActionGroup::triggered,
            this, &MainWindow::slot_rctActionTriggered);
    ui->spinBox_K->setValue(configParam.getLastKValue());
    ui->lineEdit_corr_file->setText(configParam.getCorrFileName());
    ui->spinBox_countStart->setValue(configParam.getLastCountStart());
    ui->spinBox_countEnd->setValue(configParam.getLastCountEnd());
    ui->doubleSpinBox_distanceX->setValue(configParam.getLastDistanceX());
    ui->doubleSpinBox_distanceX->setValue(configParam.getLastDistanceY());
    ui->doubleSpinBox_scaleX->setValue(configParam.getLastScaleX());
    ui->doubleSpinBox_scaleY->setValue(configParam.getLastScaleY());
    ui->doubleSpinBox_radius->setValue(configParam.getLastRadius());
    ui->doubleSpinBox_length->setValue(configParam.getLastLength());

    if(!loadCards()){
        exit(0);
    }
}

MainWindow::~MainWindow()
{  
    configParam.setLastKValue(ui->spinBox_K->value());
    configParam.setCorrFileName(ui->lineEdit_corr_file->text());
    configParam.setLastCountStart(ui->spinBox_countStart->value());
    configParam.setLastCountEnd(ui->spinBox_countEnd->value());
    configParam.setLastDistanceX(ui->doubleSpinBox_distanceX->value());
    configParam.setLastDistanceY(ui->doubleSpinBox_distanceY->value());
    configParam.setLastScaleX(ui->doubleSpinBox_scaleX->value());
    configParam.setLastScaleY(ui->doubleSpinBox_scaleY->value());
    configParam.setLastRadius(ui->doubleSpinBox_radius->value());
    configParam.setLastLength(ui->doubleSpinBox_length->value());
    configParam.writeToFile();
    free_rtc5_dll();
    delete ui;
}

/**
 * @brief loadCards 加载控制卡
 */
bool MainWindow::loadCards()
{
    const auto initDLL = init_rtc5_dll();
    if (initDLL & ERROR_VERSION_MISMATCH)
    {
        QMessageBox::critical(this, "错误", "文件版本错误");
        return false;
    }
    else if (initDLL & ERROR_NO_CARD)
    {
        QMessageBox::critical(this, "错误", "没有找到可用的控制卡");
        return false;
    }else if(initDLL ^ ERROR_NO_ERROR)
    {
        QMessageBox::critical(this, "错误", QString("初始化失败,错误码:%1").arg(initDLL));
        return false;
    }

    QList<CardInfo> mCardInfos;
    const int foundCards = rtc5_count_cards();
    cardInfos.clear();
    for (int card = 1; card <= foundCards; card++)
    {
        CardInfo info(card);
        info.type = "RTC5 PCIe Board";
        mCardInfos.append(info);

        uint sn = n_get_serial_number(info.mId);
        info.sn = QString::number(sn);

        QAction *newAction = new QAction(info.sn, ui->cardList);
        newAction->setObjectName("Card");
        newAction->setCheckable(true);
        rtcCardsGroup->addAction(newAction);
        ui->cardList->addAction(newAction);

        connect(cardUtil, SIGNAL(sig_markStarted(int)),
                this, SLOT(slot_markStart(int)));
        connect(cardUtil, SIGNAL(sig_markFinished(int, int, int)),
                this, SLOT(slot_markFinished(int, int, int)));

        if(card == 1){
            uint s = select_rtc(info.mId);
            if(s > 0){
                newAction->setChecked(true);
                ui->statusBar->showMessage("当前选中卡:" + info.sn);
                const auto loadProgram = load_program_file(nullptr);
                if(loadProgram != ERROR_NO_ERROR){
                    QMessageBox::critical(this, "错误",
                                          "load_program_file失败，错误码：" + loadProgram);
                    return false;
                }
                const auto loadCorrection = load_correction_file("Cor_1to1.ct5", 1, 2);
                if(loadCorrection != ERROR_NO_ERROR){
                    QMessageBox::critical(this, "错误",
                                          "load_correction_file失败，错误码：" + loadCorrection);
                    return false;
                }
            }else{
                QMessageBox::critical(this, "错误",
                                      "控制卡选中失败，错误码：" + get_last_error());
            }
        }
        cardInfos.append(info);
    }
    cardUtil->setKValue(ui->spinBox_K->value());
    return true;
}

void MainWindow::slot_rctActionTriggered(QAction *action)
{
    int pos = -1;
    for(int i = 0; i < cardInfos.size(); i++){
        CardInfo info = cardInfos.at(i);
        if(info.sn == action->text()){
            pos = i;
            break;
        }
    }
    if(pos >= 0){
        CardInfo info = cardInfos.at(pos);
        uint s = select_rtc(info.mId);
        if(s > 0){
            action->setChecked(true);
            ui->statusBar->showMessage("当前选中卡:" + info.sn);
            const auto loadProgram = load_program_file(nullptr);
            if(loadProgram != 0){
                qDebug() << "控制卡初始化失败" << loadProgram;
            }
        }else{
            qDebug() << "控制卡选中失败" << get_last_error();
        }
    }
}

void MainWindow::on_pushButton_loadfile_clicked()
{
    QString filter = "ct5 (*.ct5)";
    QString filePath = QFileDialog::getOpenFileName(this, tr("选择校正文件"),
                                                    QDir::currentPath(),
                                                    filter);
    if (filePath.isEmpty()) {
        return;
    }

    ui->lineEdit_corr_file->setText(filePath);
    const auto loadCorrection = load_correction_file(filePath.toLocal8Bit().data(), 1, 2);
    if(loadCorrection == ERROR_NO_ERROR){
        int k = get_table_para(1, 1);
        cardUtil->setKValue(k);
        ui->spinBox_K->setValue(k);
    }else{
        qDebug() << QString("加载校正文件失败,错误代码=>") << get_last_error();
    }
}

void MainWindow::on_pushButton_flyRun_clicked()
{
    MarkerPath path;
    path.laserOnMove(QPointF(0, 0), 1000);
    QList<MarkerPath> list;
    list.append(path);
    if(!mark(list, true, false)){
        QMessageBox::critical(this, tr("错误"),
                              tr("标刻失败,RTC卡可能不在线,请重新初始化!"));
    }
}

void MainWindow::on_pushButton_flyCalc_clicked()
{
    int countStart = ui->spinBox_countStart->value();
    int countEnd = ui->spinBox_countEnd->value();
    double disX = ui->doubleSpinBox_distanceX->value();
    double disY = ui->doubleSpinBox_distanceY->value();
    int k = ui->spinBox_K->value();
    double scaleX = 0;
    if(disX > 0){
        scaleX = k * disX / (countEnd - countStart);
    }
    ui->doubleSpinBox_scaleX->setValue(scaleX);
    double scaleY = 0;
    if(disY > 0){
        scaleY = k * disY / (countEnd - countStart);
    }
    ui->doubleSpinBox_scaleY->setValue(scaleY);
}

void MainWindow::on_pushButton_mark_clicked()
{
    double radius = ui->doubleSpinBox_radius->value();
//    double total = ui->doubleSpinBox_length->value();
//    int count = total / (radius * 4);

//    QList<MarkerPath> list;
//    for(int i = 0; i < count; i++){
//        MarkerPath path;
//        path.moveTo(QPointF(0, 0));
//        path.arcTo(QPointF(-(radius), 0), -180);
//        path.arcTo(QPointF(-(3 * radius), 0), 180);
//        path.setWidth(radius * 4);
//        list.append(path);
//    }

    QList<MarkerPath> list;
    for(int i = 0; i < 1; i++){
        MarkerPath path1;
        path1.moveTo(QPointF(0, 0));
        path1.arcTo(QPointF(-(radius), 0), 360);
        path1.setWidth(radius * 2);
        list.append(path1);

        MarkerPath path2;
        path2.moveTo(0, 10);
        path2.lineTo(-10, 10);
        path2.lineTo(-10, -10);
        path2.lineTo(0, -10);
        path2.lineTo(0, 10);
        path2.setWidth(20);
        list.append(path2);


        MarkerPath path3;
        path3.moveTo(0, 0);
        path3.lineTo(-10, 10);
        path3.lineTo(-10, -10);
        path3.lineTo(0, 0);
        path3.setWidth(10);
        list.append(path3);
    }

    if(!mark(list, true, ui->checkBox_fly->isChecked())){
        QMessageBox::critical(this, tr("错误"),
                              tr("标刻失败,RTC卡可能不在线,请重新初始化!"));
    }
}

bool MainWindow::mark(QList<MarkerPath> list, bool flyCorr, bool fly)
{
    if(list.size() <= 0){
        QMessageBox::critical(nullptr, "错误", "没有可打印的图形");
        return false;
    }

    cardUtil->setKValue(ui->spinBox_K->value());
    LaserParams laserParams;
    laserParams.readFromFile();
    laserParams.laserDevice().setLaserMode(LaserMode::QCW);
    laserParams.laserDevice().setPower(20);
    MarkerParam markerParam = laserParams.toMarkParams();
    markerParam.fly2DParam().setEnable(fly);
    markerParam.fly2DParam().setCorrable(flyCorr);
    markerParam.fly2DParam().setScaleX(ui->doubleSpinBox_scaleX->value());

    MarkerJob markerJob;
    markerJob.setPathList(list);
    markerJob.setMarkerParam(markerParam);
    markerJob.setLoopExcute(false);
    cardUtil->addJob(markerJob);
    return true;
}

void MainWindow::slot_markStart(int)
{
    ui->statusBar->showMessage(QString("标刻开始"));
}

void MainWindow::slot_markFinished(int, int, int time)
{
    long enc00 = 0;
    long enc10 = 0;
    long enc01 = 0;
    long enc11 = 0;
    cardUtil->readEncoder(enc00, enc10, enc01, enc11);
    qDebug() << "enc00=" << enc00 << "enc01=" << enc01
             << "enc10=" << enc10 << "enc11=" << enc11;
    ui->statusBar->showMessage(QString("标刻结束,共%1ms").arg(time));
}

void MainWindow::slot_logMessage(int code, QString err)
{
    if(code >= 1){
        QMessageBox::critical(nullptr, "错误", err);
    }else{
        ui->statusBar->showMessage(err);
    }
}

void MainWindow::on_pushButton_stop_clicked()
{
    cardUtil->stopMark();
}

void MainWindow::on_pushButton_readEncoder_clicked()
{
    long enc00 = 0;
    long enc10 = 0;
    long enc01 = 0;
    long enc11 = 0;
    cardUtil->readEncoder(enc00, enc10, enc01, enc11);
    qDebug() << "enc00=" << enc00 << "enc01=" << enc01
             << "enc10=" << enc10 << "enc11=" << enc11;
    ui->spinBox_countStart->setValue(enc00);
    ui->spinBox_countEnd->setValue(enc01);
}

void MainWindow::on_pushButton_getEncoder_clicked()
{
    long enc1 = 0;
    long enc2 = 0;
    cardUtil->getEncoder(enc1, enc2);
    qDebug() << "enc1=" << enc1 << "enc2=" << enc2;
    ui->spinBox_enc1->setValue(enc1);
    ui->spinBox_enc2->setValue(enc2);
}

void MainWindow::on_checkBox_external_start_clicked(bool checked)
{
    cardUtil->setControlMode(checked ? 1U : 0U);
}
